@file:Suppress("unused")

package top.kikt.book.util

import okhttp3.*
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody
import java.net.Proxy
import java.nio.charset.Charset

object HttpUtils {

    private val client: OkHttpClient = OkHttpClient.Builder()
        .cookieJar(MyCookieJar())
        .build()

    fun getClient(): OkHttpClient = client

    private val globalHeaders = HashMap<String, String>()

    fun addGlobalHeader(name: String, value: String) {
        globalHeaders[name] = value
    }

    fun get(httpUrl: HttpUrl, headers: Map<String, String> = emptyMap(), proxy: Proxy? = null): Response {
        val request = Request.Builder()
            .url(httpUrl)
            .apply {
                headers.forEach(::addHeader)
                globalHeaders.forEach(::addHeader)
            }
            .get()
            .build()

        if (proxy != null) {
            val fakeClient = client.newBuilder()
                .proxy(proxy)
                .build()

            return fakeClient.newCall(request).execute()
        }

        return client.newCall(request)
            .execute()
    }

    fun get(url: String, headers: Map<String, String> = emptyMap(), proxy: Proxy? = null): Response {
        return get(url.toHttpUrl(), headers, proxy)
    }

    fun Response.string(charset: Charset = Charset.defaultCharset()): String? {
        return body?.bytes()?.toString(charset)
    }

    fun decodeCurlCommandHeaders(command: String): Map<String, String> {
        val map = mutableMapOf<String, String>()
        val regex = Regex("""-H '([^:]+): (.+)'""")
        val matches = regex.findAll(command)
        matches.forEach {
            val (key, value) = it.destructured
            map[key] = value
        }

        return map
    }

    fun postForm(httpUrl: HttpUrl, formData: Map<String, String>, headers: Map<String, String>): Response {
        val body = formData.entries.joinToString("&") { (key, value) ->
            "$key=$value"
        }.toRequestBody(
            "application/x-www-form-urlencoded".toMediaType()
        )

        val request = Request.Builder()
            .url(httpUrl)
            .apply {
                headers.forEach(::addHeader)
                globalHeaders.forEach(::addHeader)
            }
            .post(body)
            .build()

        return client.newCall(request)
            .execute()
    }
}